package top.wecreate.snet;

import java.util.List;
import java.util.Map;

import top.wecreate.snet.SnetConnectionRunnable.OnConnectionResultListener;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.text.TextUtils;

/**
 * 
 * @author Administrator
 * 
 * @param <T>
 *            正常返回的数据类型
 * @param <E>
 *            异常返回的数据类型
 */
public abstract class SnetBaseConnection<T, E> {

	private String url;
	private Map<String, String> requestHeaders;
	private Map<String, String> requestParams;

	private OnConnectionResultListener listener = new OnConnectionResultListener() {

		@Override
		public void onResponse(int responseCode,
				Map<String, List<String>> headers, byte[] responseBody) {
			processResponseBackground(responseCode, headers, responseBody);
		}

		@Override
		public void onException(Exception e) {
			processExceptionBackground(e);
		}
	};

	/**
	 * 服务器有数据返回，回调这个方法。须在这个方法中对返回结果进行处理。比如解析json之类的操作。
	 * <p>
	 * <NOTE>这个操作是在线程中进行的。不可对View进行操作。
	 * 
	 * @param responseCode
	 *            返回码
	 * @param responseHeaders
	 *            返回的头信息
	 * @param responseBody
	 *            返回的值
	 */
	protected abstract void processResponseBackground(int responseCode,
			Map<String, List<String>> responseHeaders, byte[] responseBody);

	/**
	 * 请求出现问题，比如连接超时之类的。
	 * <p>
	 * <NOTE>这个操作是在线程中进行的。不可对View进行操作。
	 * 
	 * @param e
	 *            出现的异常
	 */
	protected abstract void processExceptionBackground(Exception e);
	
	/**
	 * 设置测试返回的response数据
	 * @return
	 */
	protected abstract TestResponse fillTestResponse();
	
	/**
	 * 设置测试返回的exception数据
	 * @return
	 */
	protected abstract Exception fillTestException();

	/**
	 * 设置最终返回的成功结果
	 * 
	 * @param success
	 */
	protected void setSuccessResult(T success) {
		Message msg = handler.obtainMessage();
		msg.what = SnetHandler.WHAT_SUCCESS;
		msg.obj = success;
		handler.sendMessage(msg);
	}

	/**
	 * 设置最终返回的失败结果
	 * 
	 * @param fail
	 */
	protected void setFailResult(E fail) {
		Message msg = handler.obtainMessage();
		msg.what = SnetHandler.WHAT_FAIL;
		msg.obj = fail;
		handler.sendMessage(msg);
	}

	private SnetHandler handler = new SnetHandler() {
		@SuppressWarnings("unchecked")
		public void handleMessage(android.os.Message msg) {
			if (msg.what == SnetHandler.WHAT_SUCCESS) {
				if (msg.obj == null) {
					onSuccess(null);
				} else {
					onSuccess((T) msg.obj);
				}
			} else if (msg.what == SnetHandler.WHAT_FAIL) {
				if (msg.obj == null) {
					onFail(null);
				} else {
					onFail((E) msg.obj);
				}
			} else {

			}
		};
	};

	private static class SnetHandler extends Handler {
		/**
		 * 消息类型：服务器成功返回所需信息
		 */
		public static final int WHAT_SUCCESS = 0;
		/**
		 * 消息类型：服务器出现异常或者请求结果出错
		 */
		public static final int WHAT_FAIL = 1;

		public SnetHandler() {
			// 保证是主线程的Looper
			super(Looper.getMainLooper());
		}
	}

	/**
	 * 通过{@code setSuccessResult}接收到成功消息之后，回调给主线程。
	 * <p>
	 * 这是在主线程中返回的，可以对View进行操作。
	 * 
	 * @param result
	 */
	public abstract void onSuccess(T result);

	/**
	 * 通过{@code setFailResult}接收到成功消息之后，回调给主线程。
	 * <p>
	 * 这是在主线程中返回的，可以对View进行操作。
	 * 
	 * @param result
	 */
	public abstract void onFail(E result);

	public SnetBaseConnection(ConnetionBuilder builder) {
		this.url = builder.url;
		this.requestHeaders = builder.headers;
		this.requestParams = builder.params;
	}

	/**
	 * 发起get请求
	 */
	public void get() {
		request(SnetConnectionRunnable.GET);
	}

	/**
	 * 发起post请求
	 */
	public void post() {
		request(SnetConnectionRunnable.POST);
	}

	// 发起请求
	private void request(String method) {
		if (TextUtils.isEmpty(url)) {
			throw new IllegalArgumentException("请求地址为空");
		}

		SnetConnectionRunnable connection = new SnetConnectionRunnable(method,
				url, listener) {

			@Override
			protected TestResponse getTestResponse() {
				return fillTestResponse();
			}

			@Override
			protected Exception getTestException() {
				return fillTestException();
			}
		};

		if (requestHeaders != null && !requestHeaders.isEmpty()) {
			connection.setHeaders(requestHeaders);
		}

		if (requestParams != null && !requestParams.isEmpty()) {
			connection.setParams(requestParams);
		}

		SnetConnectionPool.getInstance().excute(connection);
	}

	/**
	 * 获取请求的地址
	 * 
	 * @return
	 */
	public String getUrl() {
		return url;
	}

	/**
	 * 获取请求头
	 * 
	 * @return
	 */
	public Map<String, String> getRequestHeaders() {
		return requestHeaders;
	}

	/**
	 * 获取请求参数
	 * 
	 * @return
	 */
	public Map<String, String> getRequestParams() {
		return requestParams;
	}

	/**
	 * 请求构造器
	 * 
	 * @author dell
	 * 
	 */
	public static class ConnetionBuilder {
		private String url;
		private Map<String, String> headers;
		private Map<String, String> params;

		/**
		 * 请求构造器
		 * 
		 * @param url
		 *            请求的地址
		 */
		public ConnetionBuilder(String url) {
			this.url = url;
		}

		/**
		 * 设置请求的头信息
		 * 
		 * @param headers
		 */
		public void setRequestHeaders(Map<String, String> headers) {
			this.headers = headers;
		}

		/**
		 * 设置请求的参数信息
		 * 
		 * @param params
		 */
		public void setRequestParams(Map<String, String> params) {
			this.params = params;
		}
	}

}
